package edu.ivanov.apm.chaos;

/**
 * Черепашка, которая ходит по плоскости.
 *
 * Ось абсцисс направлена вправо, ось ординат - вниз.
 *
 * Направление черепашки задаётся углом, отсчитываемым от положительного
 * направления оси абсцисс против часовой стрелки.
 *
 * User: Илья
 * Date: 08.10.13
 * Time: 21:07
 */
public class Turtle {

	protected enum Motion {
		GO,
		JUMP
	}

	// Текущая позиция черепашки.
	private Position position = new Position(0, 0, 0);

	/**
	 * Перемещает черепашку из текущего положения в текущем направлении на заданное расстояние.
	 *
	 * @param s Расстояние для перемещения.
	 */
	public void go(double s) {
		move(s, Motion.GO);
	}

	/**
	 * Перемещает черепашку из текущего положения в текущем направлении на заданное расстояние.
	 * При этом черепашка НЕ прорисовывает свой путь.
	 *
	 * @param s Расстояние для перемещения.
	 */
	public void jump(double s) {
		move(s, Motion.JUMP);
	}

	/**
	 * Поворачивает черепашку на заданный угол.
	 * Положительный угол задаёт поворт по часвой стрелке.
	 * Отрицательный угол задаёт поворот против часовой стрелки.
	 *
	 * @param phi Угол в радианах.
	 */
	public void rotate(double phi) {
		position = new Position(position.getX(), position.getY(), position.getAlpha() + phi);
	}

	/**
	 * @param position Устанавливает позицию черепашки.
	 */
	public void setPosition(Position position) {
		if (position == null)
			throw new RuntimeException("Не задана позиция для установки черепашки");

		moved(this.position, position, Motion.JUMP);
		this.position = position;
	}

	/**
	 * @return Текущая позиция черепашки.
	 */
	public Position getPosition() {
		return position;
	}

	private void move(double s, Motion motion) {
		if (s < 0)
			throw new RuntimeException("Расстояние для перемещения должно быть неотрицательным");
		if (Double.compare(0.0, s) == 0)
			return;

		Position newPosition = translate(s);
		moved(position, newPosition, motion);
        position = newPosition;
	}

	private Position translate(double s) {
		double alpha = position.getAlpha();
        double newX = position.getX() + s * Math.cos(alpha);
		double newY = position.getY() + s * Math.sin(alpha);

		return new Position(newX, newY, alpha);
	}


	protected void moved(Position oldPosition, Position newPosition, Motion motion) {
	}
}
